home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / i / internet / software / tuwtcpsr / ip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-23  |  9.2 KB  |  469 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <tos.h>
  5. #include <aes.h>
  6. #include "pktdrv.h"
  7. #include "ip.h"
  8. #include "arp.h"
  9. #include "icmp.h"
  10. #include "netdb.h"
  11. #include "queue.h"
  12. #include "inetcust.h"
  13.  
  14. #include "cookie.h"
  15. #include "nettrace.h"
  16.  
  17. #define Bconws(x) dpy = x;while(*dpy)(Bconout(2,*dpy++))
  18.  
  19. static char *dpy;
  20.  
  21. #define noDEBUG
  22. #define noDEBUGP
  23. #define noDEBUGA
  24. #define noDEBUGPKT
  25. #define noDEBUGF
  26.  
  27. #define AMASK   0x80L
  28. #define AADDR   0x00L
  29. #define BMASK   0xC0L
  30. #define BADDR   0x80L
  31. #define CMASK   0xE0L
  32. #define CADDR   0xC0L
  33.  
  34. #ifdef DEBUGF
  35. static char str[100];
  36. #endif
  37.  
  38. extern long q_disint(void);
  39. extern long q_enabint(void);
  40. extern long p_disint(void);
  41. extern long p_enabint(void);
  42.  
  43. INADDR lcl_inaddr = 0L;            /* my internet address */
  44. INADDR gw_inaddr = 0L;
  45. INADDR lcl_netmask = (-1L);
  46.  
  47. int ip_recv(int,char *);        /* receive handler */
  48. static struct ip_protocol
  49. {
  50.     int        (*handler)(PACKET *,int,INADDR);
  51.     int        (*du_handler)(IP *);
  52.     int        protocol;
  53. } ip_protab[MAXIP];
  54. static int ip_protocols = 0;
  55. static int ip_handle = -1;
  56. PKTQUEUE    *ip_qrecv = NULL;
  57. int ip_freecnt = 0;
  58.  
  59. extern INETCUST *custom;
  60.  
  61. INADDR iproute(INADDR);INADDR fixup_subnet_mask(INADDR, int);
  62.  
  63.  
  64. INADDR    ip_myaddr()
  65. {
  66.     return(lcl_inaddr);
  67. }
  68.  
  69. int ip_init(void)
  70. {
  71. int        nbuf;
  72. HADDR    gw_haddr;
  73. int     i;
  74.  
  75.  
  76.     lcl_inaddr = custom->inaddr;
  77.     gw_inaddr = custom->gateway;
  78.     if(arp_init() < 0)
  79.     {
  80.         fprintf(stderr,"arp-init failed\n");
  81.         return(FALSE);
  82.     }
  83.     if(gw_inaddr)
  84.     {
  85.         while((i=arp_in2haddr(gw_inaddr,gw_haddr)) == ARP_WAIT)
  86.         {
  87.             net_demux(FALSE,DEMUX);
  88.         }
  89.         if(i==ARP_OK)
  90.         {
  91. #ifdef DEBUG
  92.             printf("arp for gateway succeded\n");
  93. #endif
  94.             arp_addgw(gw_inaddr,gw_haddr);
  95.         }
  96.     }
  97.     if(custom->subnetbits)
  98.         lcl_netmask = fixup_subnet_mask(lcl_inaddr,custom->subnetbits);
  99.     if(ip_handle < 0)    /* first time called, init net */
  100.     {
  101.         ip_handle = net_open(ET_IP,ip_recv);
  102.                                     /* install demux function */
  103.         if(ip_handle < 0) return(FALSE);
  104.         if(!net_demux(TRUE,ip_demux))
  105.         {
  106.             net_release(ET_IP);
  107.             ip_handle=-1;
  108.             return(FALSE);
  109.         }
  110.         icmp_init();
  111.     }
  112.     nbuf = IP_NBUF;
  113.     ip_qrecv = ip_q_create(nbuf,0);
  114.     if(!ip_qrecv) return(FALSE);
  115.     ip_freecnt = nbuf;
  116.     return(TRUE);
  117. }
  118.  
  119. int ip_exit(void)
  120. {
  121.     while(ip_protocols)
  122.     {
  123.         ip_close(ip_protab[0].protocol);
  124.     }
  125.     ip_q_delete(ip_qrecv);
  126.     net_demux(FALSE,ip_demux);    /* uninstall demuxer */
  127.     net_release(ET_IP);
  128.     ip_handle = -1;
  129. #ifdef DEBUG
  130. printf("ip_exit\n");
  131. #endif
  132.     arp_exit();
  133.     return(TRUE);
  134. }
  135.  
  136. int ip_open(int protocol,
  137.             int (*prot_handler)(PACKET *,int,INADDR),
  138.             int (*du_handler)(IP *))
  139. {
  140. register int    i;
  141.  
  142.  
  143.     if(ip_protocols >= MAXIP) return(FALSE);
  144.     for(i=0; i<ip_protocols; i++)
  145.     {
  146.         if(ip_protab[i].protocol == protocol) return(FALSE);
  147.     }
  148.     ip_protab[ip_protocols].protocol = protocol;
  149.     ip_protab[ip_protocols].handler = prot_handler;
  150.     ip_protab[ip_protocols].du_handler = du_handler;
  151.     ip_protocols++;
  152.     return(TRUE);
  153. }
  154.  
  155.  
  156. int ip_close(int protocol)
  157. {
  158. register int i;
  159.     for(i=0; i<ip_protocols; i++)
  160.     {
  161.         if(ip_protab[i].protocol == protocol)
  162.         {
  163.             for(;i<ip_protocols-1;i++)
  164.             {
  165.                 ip_protab[i].protocol = ip_protab[i+1].protocol;
  166.                 ip_protab[i].handler = ip_protab[i+1].handler;
  167.                 ip_protab[i].du_handler = ip_protab[i+1].du_handler;
  168.             }
  169.             ip_protocols--;
  170.             return(TRUE);
  171.         }
  172.     }
  173.     return(FALSE);
  174. }
  175.  
  176.  
  177. int ip_recv(int length,char *pkt)
  178. {
  179. register int q_ok;
  180. void ip_demuxx(void);
  181.  
  182.             /* insert packet into ip receive queue */
  183.     q_ok = ip_aq_putpkt(ip_qrecv,(PACKET *)pkt);
  184.     if(q_ok) ip_demuxx();
  185.     return(q_ok);
  186. }
  187.  
  188. void ip_demuxx(void)
  189. {
  190. extern void pkt_mux(void);
  191.  
  192.      pkt_mux();    
  193. }
  194.  
  195. int ip_demux(void)
  196. {
  197. register PACKET    *pkt;
  198. register IP     *ip;
  199. register u_short    csum;
  200. register int        i;
  201. register int        len;
  202. int loop;
  203.  
  204.   for(loop = 0;loop < 2; loop++)
  205.   {
  206.     pkt = ip_aq_getpkt(ip_qrecv);    /* get packet */
  207.     if(!pkt) return(FALSE);        /* no packet there */
  208.     
  209. #ifdef DEBUG
  210. printf("ip pkt recv ");
  211.  
  212. #endif
  213.  
  214.     ip = ip_head(pkt);
  215.  
  216.     if(ip_version(ip) != IP_VERSION)
  217.     {
  218. #ifdef DEBUG
  219.     printf("bad version\n");
  220. #endif
  221.         ip_free(pkt);        /* bad version */
  222.         return(FALSE);
  223.     }
  224.     csum = ip->chksum;
  225.     ip->chksum = 0;
  226.  
  227.     if(chksum((u_short *)ip, ip_hdrlen(ip),0) != csum ) 
  228.     {
  229. #ifdef DEBUG
  230.     printf("bad chksum\n");
  231. #endif
  232.         ip_free(pkt);        /* bad checksum */
  233.         return(FALSE);
  234.     }
  235.  
  236.     ip->chksum = csum;
  237.     if (ip->dst_inaddr != lcl_inaddr )        /* not for me */
  238.         /*ip->dst_inaddr == 0xFFFFFFFFL)*/        /* or not broadcast */
  239.     {                                        /* packet not for me */
  240. #ifdef DEBUG
  241.     printf("not for me (%lx)\n",ip->dst_inaddr);
  242. #endif
  243.         ip_free(pkt);    /* drop packet */
  244.         return(FALSE);
  245.     }
  246.     if(ip->frag)
  247.     {
  248. #ifdef DEBUG
  249.         printf("ip packet FRAGMENTED\n");
  250. #endif
  251.         ip_free(pkt);    /* drop fragmented packet */
  252.         return(FALSE);
  253.     }
  254.     len = ip->length - ip_hdrlen(ip);
  255. #ifdef DEBUG
  256.     printf("protocol %2d\n",(int)ip->protocol);
  257. #endif
  258.     for(i=0; i < ip_protocols; i++)
  259.     {
  260.         if(ip_protab[i].protocol == (int)ip->protocol)
  261.         {                /* add immediate reply entry */
  262.             arp_add2tab(ip->src_inaddr,pkt->pkt_head.et_src);
  263.             if(ip_protab[i].handler)
  264.             {
  265.                 ip_protab[i].handler(pkt,len,ip->src_inaddr);
  266.                 break;
  267.             }
  268.             else
  269.             {
  270.               ip_free(pkt);
  271.               break;
  272.             }
  273.         }
  274.     }
  275.     if(i >= ip_protocols)
  276.     {
  277.                 /* no one wants packet */
  278.      if(ip->dst_inaddr == lcl_inaddr)
  279.         icmp_dstun(ip->src_inaddr,ip,ICMP_DSTPROT);
  280.  
  281.      ip_free(pkt);
  282.      return (FALSE);
  283.     }
  284.   }
  285.   return TRUE;
  286. }
  287.  
  288.  
  289. PACKET *ip_alloc(int length, int optlen)
  290. {
  291. register PACKET    *pkt;
  292. register IP        *ip;
  293.  
  294.     pkt = (PACKET *)net_pktalloc(ET_IP);
  295.     
  296.     if(!pkt)
  297.     {
  298.         Bconws("couldn't alloc IP packet\r");
  299.         return(NULL);
  300.     }
  301.  
  302.     ip = ip_head(pkt);
  303.  
  304.   /* internet header */
  305.     ip->vh = (IP_VERSION << 4) + IP_HDR + (optlen + 3)/4;
  306.     ip->tos    = IP_TOS;
  307.     ip->ident = 0;
  308.     ip->frag = 0;  /* don't fragment */
  309.     ip->length = length;
  310.     ip->ttl = IP_TTL;
  311.     ip->chksum = 0;
  312.     return(pkt);
  313. }
  314.  
  315. int ip_free(PACKET *pkt)
  316. {
  317. int i;
  318.     i = net_pktfree((char *)pkt);
  319.     if(!i)
  320.     {
  321.         Bconws("couldn't free IP packet\r");
  322.     }
  323.     return(i);
  324. }
  325.  
  326.  
  327. int ip_send(int protocol, PACKET *pkt,int length, INADDR fhost)
  328. {
  329. register IP *ip;
  330. register int i;
  331. #ifdef DEBUG
  332. printf("ip_send %d octets\n",length);
  333. #endif
  334.  
  335. #ifdef DEBUGF
  336. TRACE(">ip_send\n");
  337. #endif
  338.  
  339.  
  340.   ip = ip_head(pkt);    
  341. #ifdef DEBUGF
  342. TRACE("+>ip_send 1\n");
  343. #endif
  344.  
  345.         /* internet header */
  346.     ip->protocol = protocol;
  347.     ip->length = ip_hdrlen(ip) + length;
  348.     ip->chksum = 0;
  349.     ip->dst_inaddr = fhost;
  350.     ip->src_inaddr = lcl_inaddr;
  351.     ip->chksum = chksum((u_short *)ip, ip_hdrlen(ip),0);
  352. #ifdef DEBUGF
  353. TRACE("+>ip_send chksum\n");
  354. #endif
  355.     pkt->pkt_head.et_type = ET_IP;
  356.     net_getadr((int)sizeof(HADDR),pkt->pkt_head.et_src);
  357. #ifdef DEBUGF
  358. TRACE("+>ip_send getadr\n");
  359. #endif
  360.     fhost = iproute(fhost);
  361. #ifdef DEBUGF
  362. TRACE("+>ip_send iproute\n");
  363. #endif
  364.     while((i=arp_in2haddr(fhost,pkt->pkt_head.et_dest)) == ARP_WAIT)
  365.     {
  366.         evnt_timer(10,0);
  367.         net_demux(FALSE,DEMUX);
  368.     }
  369. #ifdef DEBUGF
  370. TRACE("+>ip_send arp done\n");
  371. #endif
  372.     if(i != ARP_OK)
  373.     {
  374. #ifdef DEBUGA
  375.         printf("arp failed\n");
  376. #endif
  377. #ifdef DEBUGF
  378. TRACE("<ip_send, arp failed\n");
  379. #endif
  380.         return(-1);
  381.     }
  382.     i = net_send(ip->length+(int)sizeof(ETH),(char *)pkt);
  383.  
  384. #ifdef DEBUGF
  385. sprintf(str,"<ip_send,ret = %d\n",i);
  386. TRACE(str);
  387. #endif
  388.  
  389.     return(i);
  390. }
  391.  
  392. /* called from ICMP */
  393. int ip_dudemux(IP *ip)
  394. {
  395. int i;
  396.     for(i=0; i<ip_protocols; i++)
  397.     {
  398.         if(ip_protab[i].protocol == (int)ip->protocol)
  399.         {
  400.             if(ip_protab[i].du_handler)
  401.             {
  402.                 ip_protab[i].du_handler(ip);
  403.                 return(TRUE);
  404.             }
  405.         }
  406.     }            /* no one wants packet */
  407.     return(ip != NULL);
  408. }
  409.  
  410. int ip_requeue(PACKET *pkt)
  411. {
  412.     if(ip_freecnt > 2)                /* keep min 2 free packets */
  413.     {
  414.         return(ip_aq_putpkt(ip_qrecv,pkt));    /* put packet again into receive queue */
  415.     }
  416.     return(FALSE);
  417. }
  418.  
  419. INADDR iproute(INADDR fhost){register int i;
  420. #ifdef DEBUGF
  421. TRACE(">ip_route\n");
  422. #endif
  423.     /* first check through the redirect table for this host */    for(i=0; i<REDIRTABLEN && redtab[i].dst_inaddr; i++)        if(redtab[i].dst_inaddr == fhost) 
  424.         {#ifdef DEBUGF
  425. TRACE("<ip_route tabentry found\n");
  426. #endif
  427.             return(redtab[i].gw_inaddr);        }        /* Check if it is on my net */    if(lcl_netmask == (-1L) || (lcl_inaddr & lcl_netmask) ==       (fhost & lcl_netmask))
  428.     {
  429. #ifdef DEBUGF
  430. TRACE("<ip_route mask fit\n");
  431. #endif
  432.         return(fhost);
  433.     }    if((fhost == 0xffffffffL))    /* broadcast */
  434.     {
  435. #ifdef DEBUGF
  436. TRACE("<ip_route broadcast\n");
  437. #endif
  438.         return(fhost);
  439.     }    /* The host isn't on a net I'm on, 
  440.         so send it to the default gateway    */    if(!gw_inaddr)
  441.     {#ifdef DEBUGF
  442. TRACE("<ip_route no gateway\n");
  443. #endif
  444.         return(fhost);
  445.     }
  446.     #ifdef DEBUGF
  447. TRACE("<ip_route gateway\n");
  448. #endif
  449.     return(gw_inaddr);}
  450.  
  451. /* Fix the subnet mask given the IP address and the number of subnet bits.
  452. */
  453. INADDR fixup_subnet_mask(INADDR lcl_inaddr, int subnet_bits) 
  454. {
  455. INADDR smask;
  456.  
  457.         /* initialize the bit field */
  458.     if((lcl_inaddr & AMASK) == AADDR)
  459.         smask = 0xFF000000L;
  460.     else if((lcl_inaddr & BMASK) == BADDR)
  461.         smask = 0xFFFF0000L;
  462.     else if((lcl_inaddr & CMASK) == CADDR)
  463.         smask = 0xFFFFFF00L;
  464.  
  465.     while(subnet_bits--)
  466.         smask = (smask >> 1) | 0x80000000L;
  467.     return(smask);
  468. }
  469.